package com.boot.netty.demo2;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class NettyServerDemo {

    /**
     * 服务端Demo实现目标
     * 1.创建BossGroup线程组，处理网络连接事件
     * 2.创建workerGroup线程组 处理网络读写事件
     * 3.创建服务端启动助手，serverBootStrap
     * 4.设置服务端通道实现方式为NIO
     * 5.设置服务端options
     * 6.创建通道初始化对象
     * 8.向pipeline中添加自定义业务初处理逻辑handler
     * 9.启动服务端并绑定端口，将异步改为同步
     * 10.关闭通道和连接池
     */

    public static void main(String[] args) throws InterruptedException {
        //1.创建BossGroup线程组，处理网络连接事件，默认线程数量与电脑处理器相关，处理器线程数*2
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        //2.创建workerGroup线程组 处理网络读写事件
        EventLoopGroup wrokerGroup = new NioEventLoopGroup();
        //3.创建服务端启动助手，serverBootStrap
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        //配置线程组
        serverBootstrap.group(bossGroup, wrokerGroup)
                .channel(NioServerSocketChannel.class)//配置Channel的实现，这里使用NIO的TCP服务端Channel
                .option(ChannelOption.SO_BACKLOG, 128)//对于阻塞的连接队列大小的配置
                .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)//开启keep-alive 会根据操作系统的设定保持长连接并检测连接可用性
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    //通过一个特殊的ChannelInboundHandler 来初始化注册到EventLoop的Channel
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new NettyServerHandlerDemo());
                    }
                });
        //启动服务并绑定端口，并且将异步改成同步
        ChannelFuture channelFuture = serverBootstrap.bind(9999).sync();
        System.out.println("服务器启动成功。。。");

        //关闭通道(停止接受新的连接)监听通道关闭的状态，这里改为同步后通道关闭才会返回
        channelFuture.channel().closeFuture().sync();
        bossGroup.shutdownGracefully();
        wrokerGroup.shutdownGracefully();

    }

}

